<?php
// +----------------------------------------------------------------------
// | UCToo [ Universal Convergence Technology ]
// +----------------------------------------------------------------------
// | Copyright (c) 2014-2021 https://www.uctoo.com All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: Patrick <contact@uctoo.com>
// +----------------------------------------------------------------------

namespace app\controller;

use app\BaseController;
use uctoo\job\SetSubscribeMessageTpl;
use uctoo\job\UploadCloudDb;
use uctoo\job\UploadCloudFunction;
use uctoo\middleware\Applet;
use uctoo\middleware\Auth;
use app\uctoo\model\saas\MerchantAccount;
use app\uctoo\model\saas\MgProfile;
use app\uctoo\model\saas\ShopAccount;
use app\uctoo\model\wechat\AppletTester;
use uctoo\ThinkEasyWeChat\MiniProgram\CloudEnv\Client;
use uctoo\ThinkEasyWeChat\MiniProgram\CloudEnv\ServiceProvider;
use uctoo\validate\File;
use EasyWeChat\OpenPlatform\Application;
use EasyWeChat\OpenPlatform\Authorizer\MiniProgram\Application as MiniProgram;
use think\exception\ValidateException;
use think\facade\Config;
use think\facade\Filesystem;
use catchAdmin\wechatopen\model\Applet as AppletModel;
use think\facade\Queue;
use think\helper\Str;

class Basic extends BaseController
{
    protected $middleware = [
        Auth::class,
        Applet::class
    ];


    /**
     * 校验微信认证昵称
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function checkNickname()
    {
        $nickname = $this->request->post('nickname/s', false);
        if (!$nickname) {
            $this->error('缺少参数');
        }
        /**
         * @var MiniProgram $mapp ;
         */
        $mapp = $this->request->mapp;
        $res = $mapp->setting->isAvailableNickname($nickname);
        $this->wxResult($res, 'check_name');
    }

    public function uploadMedia()
    {
        $file = $this->request->file('file');
        if (empty($file)) {
            $this->error('文件错误');
        }
        try {
            $this->validate(['file' => $file], File::class);
        } catch (ValidateException $e) {
            $this->error($e->getMessage());
        }
        $path = Filesystem::putFile('tmp', $file);
        if ($path) {
            $real_path = Filesystem::path($path);
            /**
             * @var MiniProgram $mapp ;
             */
            $mapp = $this->request->mapp;
            $res = $mapp->media->uploadImage($real_path);
            @unlink($real_path);
            if (isset($res['media_id'])) {
                $this->success('ok', ['media_id' => $res['media_id']]);
            }
        }
        $this->error('上传失败');
    }


    /**
     * 设置小程序昵称
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function setNickName()
    {
        $nickname = $this->request->post('nickname/s', false);
        $license_media_id = $this->request->post('license_media_id/s', false);
        if (!$nickname || !$license_media_id) {
            $this->error('缺少参数');
        }
        /**
         * @var MiniProgram $mapp ;
         */
        $mapp = $this->request->mapp;
        $res = $mapp->setting->setNickname($nickname, '', $license_media_id);
        //TODO 记录名称审核单audit_id
        $this->wxResult($res, 'set_nickname');
    }


    /**
     * 修改小程序昵称
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidArgumentException
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function updateAvatar()
    {
        $left = $this->request->post('left/f', 0.0);
        $top = $this->request->post('top/f', 0.0);
        $right = $this->request->post('right/f', 1.0);
        $bottom = $this->request->post('bottom/f', 1.0);
        $image_media_id = $this->request->post('image_media_id', false);
        if (!$image_media_id) {
            $this->error('参数错误');
        }
        /**
         * @var MiniProgram $mapp ;
         */
        $mapp = $this->request->mapp;
        $res = $mapp->account->updateAvatar($image_media_id, $left, $top, $right, $bottom);
        $this->wxResult($res, 'update_avatar');
    }

    /**
     * 设置功能介绍
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function updateSignature()
    {
        $signature = $this->request->post('signature/s', false);
        if (!$signature) {
            $this->error('缺少参数');
        }
        /**
         * @var MiniProgram $mapp ;
         */
        $mapp = $this->request->mapp;
        $res = $mapp->account->updateSignature($signature);
        $this->wxResult($res, 'update_signature');
    }

    /**
     * 设置小程序可搜索状态
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function changeSearchStatus()
    {
        $status = $this->request->post('status/d', 1);
        if (!in_array($status, [0, 1])) {
            $this->error('参数错误');
        }
        /**
         * @var MiniProgram $mapp ;
         */
        $mapp = $this->request->mapp;
        if ($status) {

            $res = $mapp->setting->setSearchable();
        } else {
            $res = $mapp->setting->setUnsearchable();
        }
        $this->wxResult($res, 'search_status');
    }

    /**
     * 获取可设置的所有类型
     */
    public function getAllCategories()
    {
        /**
         * @var MiniProgram $mapp ;
         */
        $mapp = $this->request->mapp;
        $res = $mapp->setting->getAllCategories();
        // 此处限定分类  一级：生活服务150   二级： 丽人185  休闲娱乐666(暂未开放)
        $list = $res['categories_list']['categories'];
        $limitAllIds = [150, 185, 666];
        $relation = [150 => [185, 666]];
        $categories = [];
        foreach ($list as $v) {
            if (in_array($v['id'], $limitAllIds)) {
                $v['children'] = [];
                switch ($v['level']) {
                    case 1:
                        $categories[$v['id']] = $v;
                        break;
                    case 2:
                        $categories[$v['father']]['children'][] = $v;
                        break;
                }
            }
        }
        $this->success('ok', array_values($categories));
    }

    /**
     * 添加类目
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function addCategory()
    {
        $categories = $this->request->post('categories');
        if (!$categories) {
            $this->error('类目参数错误');
        }
        /**
         * @var MiniProgram $mapp ;
         */
        $mapp = $this->request->mapp;
        $res = $mapp->setting->addCategories($categories);
        $this->wxResult($res, 'add_category');
    }

    /**
     * 删除类目
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function deleteCategory()
    {
        $first = $this->request->post('first/d');
        $second = $this->request->post('second/d');
        /**
         * @var MiniProgram $mapp ;
         */
        $mapp = $this->request->mapp;
        $res = $mapp->setting->deleteCategories($first, $second);
        $this->wxResult($res);
    }

    /**
     * 设置资料
     */
    public function setProfile()
    {
        //TODO 队列设置名称 头像 介绍 类目
        $nickname = $this->request->post('nickname/s', false);
        $license_media_id = $this->request->post('license_media_id/s', false);
        if (!$nickname || !$license_media_id) {
            $this->error('昵称参数错误');
        }
        $avatar_media_id = $this->request->post('avatar_media_id', false);
        if (!$avatar_media_id) {
            $this->error('头像参数错误');
        }
        $signature = $this->request->post('signature/s', false);
        if (!$signature) {
            $this->error('介绍参数错误');
        }
        $categories = $this->request->post('categories');
        if (!$categories) {
            $this->error('类目参数错误');
        }

        /**
         * @var MiniProgram $mapp ;
         */
        //保存信息

        $mapp = $this->request->mapp;
        $nickname_res = $mapp->setting->setNickname($nickname, '', $license_media_id);
        $avatar_res = $mapp->account->updateAvatar($avatar_media_id);
        $signature_res = $mapp->account->updateSignature($signature);
        $category_res = $mapp->setting->addCategories($categories);

        // 记录
        $profile = MgProfile::where('merchant_id', $this->request->user['uid'])->allowEmpty(true)->find();
        $profile->save([
            'merchant_id' => $this->request->user['uid'],
            'nickname' => $nickname,
            'license_media_id' => $license_media_id,
            'avatar_media_id' => $avatar_media_id,
            'signature' => $signature,
            'categories' => $categories,
            'nickname_errcode' => $nickname_res['errcode'],
            'nickname_wording' => $nickname_res['wording'] ?? '',
            'nickname_audit_id' => $nickname_res['audit_id'] ?? 0,
            'avatar_errcode' => $avatar_res['errcode'],
            'signature_errcode' => $signature_res['errcode'],
            'category_errcode' => $category_res['errcode']
        ]);

        $this->success('提交成功');
    }


    /**
     * 小程序代码提交
     */
    public function basicAssembly()
    {
        $ext_config = Config::get('ext_miniprogram');
        $ext_json = $ext_config['ext_json'];
        $applet = $this->request->applet;
        $ext_json['extAppid'] = $applet['appid'];
        if (!$applet['env']) {
            $this->error('请先开通云环境', ['app_status' => 3]);
        }
        // 校验是否开通特约支付
        if (!$applet['mchid'] && !$applet['sub_mchid']) {
            $this->error('请先开通特约商户或设置支付商户', ['app_status' => 2]);
        }
        // 校验店铺数
        $shop = ShopAccount::where('merchant_id', $this->request->user['uid'])->field('id')->find();
        if (!$shop) {
            $this->error('请先添加至少一个店铺', ['app_status' => 4]);
        }

        // 校验行业类型
        $account = MerchantAccount::with(['industry'])->where('id',$this->request->user['uid'])->field('industry_type,merchant_phone')->find();
        if(!$account['industry_type']){
            $this->error('请先设置行业类型');
        }

        /**
         * @var MiniProgram $mapp
         */
        $mapp = $this->request->mapp;
        $mapp->domain->modify(array_merge($ext_config['domain'], ['action' => 'set']));
        $ext_json['ext']['cloud_env'] = $applet['env'];
        $ext_json['ext']['current_version'] = $ext_config['user_version'];
        $ext_json['ext']['merchant_phone'] = $account['merchant_phone'];
        $ext_json['ext']['industry_type'] = $account['industry_type'];
        $ext_json = array_merge($ext_json,$account['industry']['ext_json']);
        $res = $mapp->code->commit($ext_config['template_id'], json_encode($ext_json), $ext_config['user_version'], $ext_config['user_desc']);
        $this->wxResult($res, false, function () use ($applet, $ext_config) {
            // 添加数据集合
            $dbQueueData = [
                'applet' => $applet,
                'cloud_dbs' => $ext_config['cloud_dbs']
            ];
            Queue::push(UploadCloudDb::class, $dbQueueData, 'uploadCloudDbQueue');
            // 上传云函数
            $funcQueueData = [
                'applet' => $applet,
                'cloud_functions' => $ext_config['cloud_functions']
            ];
            Queue::push(UploadCloudFunction::class, $funcQueueData, 'uploadCloudFunctionQueue');

            $this->getExperienceQrCode();
        });
    }

    /**
     * 设置订阅消息
     */
    public function setSubscribeMessage(){
        $ext_config = Config::get('ext_miniprogram');
        $tplQueueData = [
            'applet' => $this->request->applet,
            'subscribe_message_tpl' => $ext_config['subscribe_message_tpl'],
        ];
        Queue::push(SetSubscribeMessageTpl::class, $tplQueueData, 'setSubscribeMessageTplQueue');
        $this->success('ok');
    }


    /**
     * 获取体验二维码
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     * @throws \GuzzleHttp\Exception\GuzzleException
     */
    public function getExperienceQrCode()
    {
        /**
         * @var MiniProgram $mapp
         */
        $mapp = $this->request->mapp;
        $res = $mapp->code->getQrCode();
        $res->getBody()->rewind();
        $contents = $res->getBody()->getContents();

        if (empty($contents) || '{' === $contents[0]) {
            $this->error('获取失败');
        }
        $fileSystem = Filesystem::disk('public');
        $path = 'qrcode' . DIRECTORY_SEPARATOR . $this->request->applet['appid'] . '.jpg';
        $result = $fileSystem->put($path, $contents);
        if ($result) {
            $url = $this->request->domain() . $fileSystem->getConfig()->get('url') . str_replace(DIRECTORY_SEPARATOR, '/', $path);
            $this->success('ok', ['experience_qrcode' => $url . '?t=' . time()]);
        }
        $this->error('获取失败');
    }

    /**
     *  创建云环境
     */
    public function createEnv()
    {
        // 开通云环境  上传云函数
        $applet = $this->request->applet;
        if ($applet['env'] && $applet['code_secret']) {
            $this->error('已开通云环境');
        }
        $mapp = $this->request->mapp;
        /**
         * @var Client $cloud_env
         */
        $cloud_env = $mapp->register(new ServiceProvider)->cloud_env;
        $res = $cloud_env->createCloudUser();
        if (0 !== $res['errcode']) {
            $this->error('开通云环境失败',$res);
        }
        //使用appid作为envid
        $env_id = $applet['appid'] . '-' . Str::random(4, 3);
        $res = $cloud_env->createEnvAndResource($env_id, $applet['appid']);
        $this->wxResult($res, 'create_env', function ($data) use ($env_id, $applet, $cloud_env) {
            // 获取小程序代码秘钥
            $res = $cloud_env->getCodeSecret();
            if (isset($res['codesecret'])) {
                AppletModel::update(['is_create_env'=> 'true','env' => $env_id, 'code_secret' => $res['codesecret']], ['appid' => $applet['appid']]);

                $applet['env'] = $env_id;
                $applet['code_secret'] = $res['codesecret'];
                // 上传云函数
                $ext_config = Config::get('ext_miniprogram');
                //首次提交，添加数据集合
                $dbQueueData = [
                    'applet' => $applet,
                    'cloud_dbs' => $ext_config['cloud_dbs']
                ];
                Queue::push(UploadCloudDb::class, $dbQueueData, 'uploadCloudDbQueue');
                // 上传云函数
                $funcQueueData = [
                    'applet' => $applet,
                    'cloud_functions' => $ext_config['cloud_functions']
                ];
                Queue::push(UploadCloudFunction::class, $funcQueueData, 'uploadCloudFunctionQueue');

            }
        });
    }


    // 小程序版本信息
    public function xcxVersion()
    {
        $applet = $this->request->applet;
        //行业模板类型
        $data['industry'] = MerchantAccount::with(['industry'=>function($query){
            return $query->field(['id','industry_name']);
        }])->where('id',$this->request->user['uid'])->field('industry_type')->find();
        //是否开通云环境
        $data['env_btn_show'] = $applet['env'] ? false : true;
        //上次审核时间
        $data['audit_time'] = $applet['audit_time'];
        // 当前版本
        $data['current_version'] = $applet['current_version'];
        //提审版本
        $data['audit_version'] = $applet['audit_version'];
        // 最新版本
        $data['latest_version'] = Config::get('ext_miniprogram.user_version');
        // 提审
        $data['audit_btn_show'] = (!$data['env_btn_show'] && $data['latest_version'] === $data['audit_version']) ? false : true;
        // 设置订阅消息模板按钮
        $data['set_smtpl_btn_show'] = !$data['env_btn_show'] && !$data['audit_btn_show'];
        // 审核状态
        $data['audit_status'] = '-';
        // 审核信息
        $data['audit_info'] = '-';
        // 小程序二维码
        $data['qrcode_url'] = $applet['qrcode_url'];
        if ($applet['auditid']) {
            // 查询审核状态
            /**
             * @var MiniProgram $mapp
             */
            $mapp = $this->request->mapp;
            $res = $mapp->code->getAuditStatus($applet['auditid']);
            if (isset($res['status'])) {
                $statusList = AppletModel::getAuditStatusList();
                $data['audit_status'] = $statusList[$res['status']];
                $data['audit_info'] = $res['reason'] ?? '-';
                in_array($res['status'],[AppletModel::AUDIT_STATUS_FAIL,AppletModel::AUDIT_STATUS_REVOKE]) && $data['audit_btn_show'] = true;
            }
        }
        $this->success('ok', $data);
    }

    /**
     * 确认提交审核
     */
    public function submitAudit()
    {
        /**
         * @var MiniProgram $mapp
         */
        $mapp = $this->request->mapp;
        $ext_config = Config::get('ext_miniprogram');
        $res = $mapp->code->submitAudit([], null, null);
        $this->wxResult($res, 'submit_audit', function ($data) use ($ext_config) {
            // 保存auditid
            AppletModel::update(['audit_tpl_id' => $ext_config['template_id'], 'audit_version' => $ext_config['user_version'],'auditid' => $data['auditid']], ['appid' => $this->request->applet['appid']]);
        });
    }


    /**
     * 体验者设置
     */
    public function testerSetting()
    {
        $action = $this->request->get('action/s');
        $wechatId = $this->request->post('wechat_id/s', false);
        /**
         * @var MiniProgram $mapp
         */
        $mapp = $this->request->mapp;
        switch ($action) {
            case 'bind':
                if (!$wechatId) {
                    $this->error('参数错误');
                }
                $res = $mapp->tester->bind($wechatId);
                $callback = function ($data) use ($wechatId) {
                    // 记录
                    AppletTester::create([
                        'appid' => $this->request->applet['appid'],
                        'wechat_id' => $wechatId
                    ]);
                };
                break;
            case 'unbind':
                if (!$wechatId) {
                    $this->error('参数错误');
                }
                $res = $mapp->tester->unbind($wechatId);
                AppletTester::where([
                    'appid' => $this->request->applet['appid'],
                    'wechat_id' => $wechatId
                ])->delete();
                break;
            case 'list':
                $list = AppletTester::getList(['appid' => $this->request->applet['appid']]);
                $this->success('ok', $list);
                break;
            default:
                $this->error('参数错误');
                break;
        }


        $this->wxResult($res, 'tester_setting', $callback ?? null);
    }

    /**
     * 小程序基本信息
     *
     * @param Application $app
     */
    public function xcxInfo(Application $app)
    {
        $applet = $this->request->applet;
        $res = $app->getAuthorizer($applet['appid']);
        $authorizer_info = $res['authorizer_info'];
        $authorizer_info['verify_status'] = (0 === $authorizer_info['verify_type_info']['id']);
        $authorizer_info['categories'] = $authorizer_info['MiniProgramInfo']['categories'];
        $authorizer_info['visit_status'] = (0 === $authorizer_info['MiniProgramInfo']['visit_status']);
        $authorizer_info['appid'] = $applet['appid'];
        $authorizer_info['authorize_type'] = $applet['authorize_type'];
        unset($authorizer_info['service_type_info'], $authorizer_info['verify_type_info'], $authorizer_info['MiniProgramInfo'], $authorizer_info['business_info']);
        // 快速注册授权
        if (2 === $applet['authorize_type']) {
            /**
             * @var MiniProgram $mapp
             */
            $mapp = $this->request->mapp;
            $res = $mapp->account->getBasicInfo();
            $authorizer_info['extra_info'] = array_intersect_key($res, array_flip(['wx_verify_info', 'signature_info', 'head_image_info']));
        }
        $this->success('ok', $authorizer_info);
    }



}
